今天這篇開始參考這本書,看看簡單的 promise 實作 (希望看得懂),從另一個角度來理解 promise。
這個實作叫做 DemoPromise
,是一個有三個原型方法的 class:
DemoPromise.prototype.resolve(value)
DemoPromise.prototype.reject(reason)
DemoPromise.prototype.then(onFulfilled, onRejected)
也就是說這裡把 resolve
和 reject
當作方法,而不是像真的 promise 一樣是建構式的 callback 函式。
初步讓 DemoPromise
可以有一些基本功能:
then
來設定待執行的 callback (這個階段還不能鏈接)。以程式碼來說,就是可以做到這樣:
const dp = new DemoPromise();
dp.resolve('abc');
dp.then(function (value) {
console.log(value); // abc
});
then
有兩種情況:
onFulfilled
和 onRejected
排進工作 (fulfillReactions) 中,等待有結果時執行。onFulfilled
或 onRejected
then(onFulfilled, onRejected) {
const self = this;
const fulfilledTask = function () {
onFulfilled(self.promiseResult);
};
const rejectedTask = function () {
onRejected(self.promiseResult);
};
switch (this.promiseState) {
case 'pending':
this.fulfillReactions.push(fulfilledTask);
this.rejectReactions.push(rejectedTask);
break;
case 'fulfilled':
addToTaskQueue(fulfilledTask);
break;
case 'rejected':
addToTaskQueue(rejectedTask);
break;
}
}
function addToTaskQueue(task) {
setTimeout(task, 0);
}
resolve
做的事情是:如果 promise 已經 settled,則不做任何事 (因為只能 settle 一次),否則將 promise 狀態改成 'fulfilled',並將結果存進 promise 的結果屬性裡。接著執行已經排好的成功處理 (fulfillReactions)。
resolve(value) {
if (this.promiseState !== 'pending') return;
this.promiseState = 'fulfilled';
this.promiseResult = value;
this._clearAndEnqueueReactions(this.fulfillReactions);
return this; // 這樣讓後面可以鏈接
}
_clearAndEnqueueReactions(reactions) {
this.fulfillReactions = undefined;
this.rejectReactions = undefined;
reactions.map(addToTaskQueue);
}
reject
是同樣的邏輯,只是改成失敗的狀態。